/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.core.commands;

import java.util.Iterator;

import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.gef.requests.CreateRequest;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Stereotype;

import com.cea.papyrus.core.helper.IGraphElementHelper;
import com.cea.papyrus.core.helper.ModelerHelper;
import com.cea.papyrus.core.pseudoelement.UMLElementFactory;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.core.utils.LookForElement;
import com.cea.papyrus.diagraminterchange2.di2.Di2Factory;
import com.cea.papyrus.diagraminterchange2.di2.GraphElement;

/**
 * The Class Di2UMLElementCreateCommand.
 * This class is used to create the di2 element in the diagram with its UMLElement
 */
public class Di2UMLElementCreateCommand extends PapyrusCommand{

	/**
	 * The location.
	 */
	public Point location=null;

	/**
	 * The size.
	 */
	public Dimension size=null;

	/**
	 * The uml parent.
	 */
	protected Element umlParent;

	/**
	 * The uml child.
	 */
	protected Element umlChild;

	/**
	 * The parent GE.
	 */
	public GraphElement parentGE;

	/**
	 * the created graphElement*.
	 */
	protected GraphElement childGe;

	/**
	 * request that creates this command.
	 */
	protected CreateRequest createRequest;
	
	//Darpan
	public String typeDiagram;

	/**
	 * The Constructor.
	 * 
	 * @param element the element
	 * @param typeDiagram 
	 * @param parent the parent
	 */
	public Di2UMLElementCreateCommand(Object element, GraphElement parent,String typeDiagram) {
		super(element);
		this.typeDiagram = typeDiagram;
		if(elementClass!=null){
			this.imodelerFactory= ModelerHelper.getFactory(typeDiagram);
			this.elementFactory = this.imodelerFactory.getElementFactory(this.elementClass);
			parentGE=parent;

			this.setLabel("\"creation of "+ elementClass.getSimpleName()+"\"");
		}
	}

	/**
	 * 
	 * 
	 * @return 
	 */
	public boolean canExecute() {
		boolean canExecute=false;
		canExecute=((IGraphElementHelper)elementFactory).canCreateGraphElement(parentGE);
		boolean noRestriction = true;

		if ((enhancedType != null) && (enhancedType instanceof UMLElementFactory)) {
			noRestriction = ((UMLElementFactory) enhancedType).canExecute(parentGE);
		}
		
		return (canExecute && noRestriction);
	}

	/**
	 * Execute.
	 */
	public void execute(){
		try{
			umlParent=LookForElement.lookForUMLElementOf(parentGE);
		}
		catch (Exception e) {
			Debug.log(e);
		}
		umlChild=((IGraphElementHelper)elementFactory).createUMLElement(umlParent);
		this.childGe=((IGraphElementHelper)elementFactory).createGraphElement(umlChild,parentGE,location,size);
		setStereotypes(umlChild);
		setPresentation(childGe);
	}

	/**
	 * Sets the location.
	 * 
	 * @param loc the loc
	 */
	public void setLocation (Point loc) {
		this.location = loc;
	}

	/**
	 * Redo.
	 */
	public void redo(){
		((IGraphElementHelper)elementFactory).addUMLElement(umlChild,umlParent);
		((IGraphElementHelper)elementFactory).addGraphElement(childGe,parentGE);
	}

	/**
	 * Undo.
	 */
	public void undo(){
		//((INodeFactory)elementFactory).deleteGraphElement(graphGe);
		((IGraphElementHelper)elementFactory).removeGraphElement(childGe, parentGE);
		((IGraphElementHelper)elementFactory).removeUMLElement(umlChild, umlParent);

	}

	
	/**
	 * When creating an element which description is "enhancedType"
	 * this method is used to add required stereotype after creation.
	 * 
	 * @param child 
	 */
	protected void setStereotypes(Element child) {
		// Try to add stereotype if enhancedType is not null
		if ((enhancedType == null)
				|| (!(enhancedType instanceof UMLElementFactory)) ) {
			return;
		}

		UMLElementFactory enhancedUMLType = (UMLElementFactory) enhancedType;
		com.cea.papyrus.umlutils.Element childElt = new com.cea.papyrus.umlutils.Element(child);
		Iterator<String> stereotypeIt = enhancedUMLType.getStereotypes().iterator();

		while (stereotypeIt.hasNext()) {
			childElt.toggleStereotype(stereotypeIt.next(), true);
		}
	}

	/**
	 * When creating an element which description is "enhancedType"
	 * this method is used to select presentation just after creation.
	 * 
	 * @param child 
	 */
	protected void setPresentation(GraphElement child) {
		// Try to set presentation if enhancedType is not null
		if ((enhancedType == null)
				|| (!(enhancedType instanceof UMLElementFactory)) ) {
			return;
		}

		UMLElementFactory enhancedUMLType = (UMLElementFactory) enhancedType;

		if (child.getSemanticModel() != null) {
			child.getSemanticModel().setPresentation(enhancedUMLType.getPresentation());
			
			//for each stereotype add a property to the node, used to display the stereotype
			Iterator stereotypeList = umlChild.getAppliedStereotypes().iterator();
			while(stereotypeList.hasNext()){
				// property to add creation
				com.cea.papyrus.diagraminterchange2.di2.Property property = Di2Factory.eINSTANCE.createProperty();
				property.setKey(ModelerHelper.PROPERTY_STEREOTYPE_DISPLAY);
				property.setValue(((Stereotype)stereotypeList.next()).getQualifiedName());
	
				// add the property
				child.getProperty().add(property);
			}
		}
	}

	/**
	 * Sets the size.
	 * 
	 * @param dim the dim
	 */
	public void setSize(Dimension dim) {
		this.size=dim;
	}

	/**
	 * 
	 * 
	 * @return 
	 */
	public CreateRequest getCreateRequest() {
		return createRequest;
	}

	/**
	 * 
	 * 
	 * @param createRequest 
	 */
	public void setCreateRequest(CreateRequest createRequest) {
		this.createRequest = createRequest;
	}


}
